package cranim.simulation;

import cranim.Constants;
import cranim.simulation.units.AbstractUnit;
import java.util.UUID;

/**
 *
 * @author Benedikt
 */
public class Unit implements Constants{
    
    public AbstractUnit abstractunit;
    public int arms, shields, hull, fullhull, shotsfired;
    public boolean destroyFlag = false;
    public Fleet fleet;
    public UUID id;
     
    public Unit(Fleet fleet, int armsTech, int shieldsTech, int hullTech, AbstractUnit abstractunit){
        id = UUID.randomUUID();
        this.fleet = fleet;
        init(armsTech, shieldsTech, hullTech, abstractunit);
    }
    
    public Unit(Unit unit, Fleet fleet){
        this.id = unit.getID();
        this.abstractunit = unit.getAbstractUnit();
        this.arms = unit.arms;        
        this.shields = unit.shields;
        this.hull = unit.hull;
        this.fullhull = unit.fullhull;
        this.shotsfired = unit.shotsfired;
        this.destroyFlag = unit.destroyFlag;
        this.fleet = fleet;
    }
    
    public AbstractUnit getAbstractUnit() {
        return abstractunit;
    }
    
    public int getType(){
        return getAbstractUnit().getType();
    }
    
    public Fleet getFleet(){
        return fleet;
    }

    public int getRF(Unit opponent){
        return getAbstractUnit().getAbstractRF(opponent);
    }
    
    public UUID getID(){
        return id;
    }
    
    public final void init(int armsTech, int shieldsTech, int hullTech, AbstractUnit abstractunit){
        this.abstractunit = abstractunit;
        arms = (int)Math.round((double)getAbstractUnit().baseArms * (1.0 + armsTech/10.0));
        shields = (int)Math.round((double)getAbstractUnit().baseShields * (1.0 + shieldsTech/10.0));
        fullhull = (int)Math.round((double)getAbstractUnit().baseHull * (1.0 + hullTech/10.0));
        hull = fullhull;
    }
    
    
    public void rechargeShields(int shieldsTech){        
        shields = (int)Math.round((double)getAbstractUnit().baseShields * (1.0 + shieldsTech/10.0));
        shotsfired = 0;
    }
    
    public int getFullHull(int hullTech){
        return (int)Math.round(getAbstractUnit().baseHull * ((1.0 + hullTech)/10.0));
    }
    
    public boolean getDestroyFlag(){
        return destroyFlag;
    }
    
    public Shot shoot(Fleet opponentFleet){
        Unit target = opponentFleet.getRandomUnit();
        //System.out.println(getAbstractUnit().toString()+" shoots for the "+(shotsfired+1)+"th time, target: "+target.getAbstractUnit().toString());
        int[] dmg = target.getShot(arms);
        shotsfired++;
        //Rapid Fire
        int rf = getRF(target);
        //System.out.println("Rapid fire is "+rf);
        if(rf > 0 && shotsfired < MAX_SHOTS){
            if(Math.random() <= ((double)rf-1.0)/(double)rf){
                //System.out.println("Rapid fire shoots");
                shoot(opponentFleet);
            }
        }
        Shot shot = new Shot(this, target, dmg);
        return shot;
    }
    
    public int[] getShot(int arms){
        //System.out.println(getAbstractUnit().toString()+" gets shot for "+arms+" damage, before: shields "+shields+" and hull "+hull);
        
        //Explosion chance
        if((double)hull < EXPLOCHANCE*(double)fullhull){
            if(Math.random() >= (double)hull/(double)fullhull){
                hull = 0;
                destroyFlag = true;
            }
        }
        //1% rule
        if(arms < (double)shields*PERCENT_RULE){
            int[] dmg = {0, 0};
            return dmg;
        }
        else{
            int totalHP = hull+shields;
            //More damage than shields+hull
            if(arms >= totalHP){
                int[] dmg = {shields, hull};
                shields = 0;
                hull = 0;
                destroyFlag = true;
                return dmg;
            }
            //More damage than shields
            else if(arms >= shields){
                arms -= shields;
                int[] dmg = {shields, arms};
                shields = 0;
                hull -= arms;
                return dmg;
            }
            //Less damage than shields
            else if(arms < shields){
                int[] dmg = {arms, 0};
                shields -= arms;
                return dmg;
            }
            //Should not get here
            else{
                System.out.println("Critical Error");
                System.out.println("Damage does not fit");
                int[] dmg = {0, 0};
                return dmg;
            }
        }
    }
    
}
